// copyright jyz.2024

#pragma once

#include "CoreMinimal.h"
#include "AbilitySystemComponent.h"
#include "AttributeSet.h"
#include "AuraAttributeSet.generated.h"


#define ATTRIBUTE_ACCESSORS(ClassName, PropertyName) \
	GAMEPLAYATTRIBUTE_PROPERTY_GETTER(ClassName, PropertyName) \
	GAMEPLAYATTRIBUTE_VALUE_GETTER(PropertyName) \
	GAMEPLAYATTRIBUTE_VALUE_SETTER(PropertyName) \
	GAMEPLAYATTRIBUTE_VALUE_INITTER(PropertyName)

//DECLARE_DELEGATE_RetVal(FGameplayAttribute,FAttributeSignature)

using FAttributeFuncPtr = TBaseStaticDelegateInstance<FGameplayAttribute(),FDefaultDelegateUserPolicy>::FFuncPtr;

template<class T>
using TStaticFuncPtr = typename TBaseStaticDelegateInstance<T,FDefaultDelegateUserPolicy>::FFuncPtr;


USTRUCT()
struct FEffectProperties
{
	GENERATED_BODY()
public:
	FEffectProperties()
		: AbilitySystemComponent(nullptr)
		, AvatarActor(nullptr)
		, Controller(nullptr)
		, Character(nullptr)
	{
		
	}
	UPROPERTY() 
	UAbilitySystemComponent* AbilitySystemComponent;
	UPROPERTY()
	AActor* AvatarActor;
	UPROPERTY()
	AController* Controller;
	UPROPERTY()
	ACharacter* Character;
};
UCLASS()
class AURARPGDEMO_API UAuraAttributeSet : public UAttributeSet
{
	GENERATED_BODY()
public:
	UAuraAttributeSet();
	virtual void GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const override;
	virtual void PreAttributeBaseChange(const FGameplayAttribute& Attribute, float& NewValue) const override;
	virtual void PostGameplayEffectExecute(const FGameplayEffectModCallbackData& Data) override;


	TMap<FGameplayTag,TStaticFuncPtr<FGameplayAttribute() >> AttributeDelegateMap;
	
	//TMap<FGameplayTag,FGameplayAttribute(*)()> AttributeDelegateMap; 
	//TMap<FGameplayTag,FAttributeSignature> AttributeDelegateMap; 


	/*
	 * Primary Attributes(主要的)
	 */
	//力量
	UPROPERTY(BlueprintReadOnly,ReplicatedUsing = OnRep_Strength,Category= "Vital Attibutes")
	FGameplayAttributeData Strength;
	ATTRIBUTE_ACCESSORS(UAuraAttributeSet,Strength)
	UFUNCTION()
	void OnRep_Strength(const FGameplayAttributeData& OldStrength) const;

	//智力
	UPROPERTY(BlueprintReadOnly,ReplicatedUsing = OnRep_Intelligence,Category= "Vital Attibutes")
	FGameplayAttributeData Intelligence;
	ATTRIBUTE_ACCESSORS(UAuraAttributeSet,Intelligence)
	UFUNCTION()
	void OnRep_Intelligence(const FGameplayAttributeData& OldIntelligence) const;

	//恢复力
	UPROPERTY(BlueprintReadOnly,ReplicatedUsing = OnRep_Resilience,Category= "Vital Attibutes")
	FGameplayAttributeData Resilience;
	ATTRIBUTE_ACCESSORS(UAuraAttributeSet,Resilience)
	UFUNCTION()
	void OnRep_Resilience(const FGameplayAttributeData& OldResilience) const;

	//活力
	UPROPERTY(BlueprintReadOnly,ReplicatedUsing = OnRep_Vigor,Category= "Vital Attibutes")
	FGameplayAttributeData Vigor;
	ATTRIBUTE_ACCESSORS(UAuraAttributeSet,Vigor)
	UFUNCTION()
	void OnRep_Vigor(const FGameplayAttributeData& OldVigor) const;

	
	//次要属性（依赖主要属性）--->Secondary Attributes
	//护甲
	UPROPERTY(BlueprintReadOnly,ReplicatedUsing = OnRep_Armor,Category= "Secondary Attributes")
	FGameplayAttributeData Armor;
	ATTRIBUTE_ACCESSORS(UAuraAttributeSet,Armor)
	UFUNCTION()
	void OnRep_Armor(const FGameplayAttributeData& OldArmor) const;

	//穿甲
	UPROPERTY(BlueprintReadOnly,ReplicatedUsing = OnRep_ArmorPiercing,Category= "Secondary Attributes")
	FGameplayAttributeData ArmorPiercing;
	ATTRIBUTE_ACCESSORS(UAuraAttributeSet,ArmorPiercing)
	UFUNCTION()
	void OnRep_ArmorPiercing(const FGameplayAttributeData& OldArmorPiercing) const;

	//格挡率
	UPROPERTY(BlueprintReadOnly,ReplicatedUsing = OnRep_BlockChance,Category= "Secondary Attributes")
	FGameplayAttributeData BlockChance;
	ATTRIBUTE_ACCESSORS(UAuraAttributeSet,BlockChance)
	UFUNCTION()
	void OnRep_BlockChance(const FGameplayAttributeData& OldBlockChance) const;

	//暴击率
	UPROPERTY(BlueprintReadOnly,ReplicatedUsing = OnRep_CriticalChance,Category= "Secondary Attributes")
	FGameplayAttributeData CriticalChance;
	ATTRIBUTE_ACCESSORS(UAuraAttributeSet,CriticalChance)
	UFUNCTION()
	void OnRep_CriticalChance(const FGameplayAttributeData& OldCriticalChance) const;

	//暴击伤害
	UPROPERTY(BlueprintReadOnly,ReplicatedUsing = OnRep_CriticalDamage,Category= "Secondary Attributes")
	FGameplayAttributeData CriticalDamage;
	ATTRIBUTE_ACCESSORS(UAuraAttributeSet,CriticalDamage)
	UFUNCTION()
	void OnRep_CriticalDamage(const FGameplayAttributeData& OldCriticalDamage) const;

	//暴击抗性
	UPROPERTY(BlueprintReadOnly,ReplicatedUsing = OnRep_CriticalHitResistance,Category= "Secondary Attributes")
	FGameplayAttributeData CriticalHitResistance;
	ATTRIBUTE_ACCESSORS(UAuraAttributeSet,CriticalHitResistance)
	UFUNCTION()
	void OnRep_CriticalHitResistance(const FGameplayAttributeData& OldCriticalHitResistance) const;

	//每秒回血能力
	UPROPERTY(BlueprintReadOnly,ReplicatedUsing = OnRep_HealthRegeneration,Category= "Secondary Attributes")
	FGameplayAttributeData HealthRegeneration;
	ATTRIBUTE_ACCESSORS(UAuraAttributeSet,HealthRegeneration)
	UFUNCTION()
	void OnRep_HealthRegeneration(const FGameplayAttributeData& OldHealthRegeneration) const;

	//每秒回蓝能力
	UPROPERTY(BlueprintReadOnly,ReplicatedUsing = OnRep_ManaRegeneration,Category= "Secondary Attributes")
	FGameplayAttributeData ManaRegeneration;
	ATTRIBUTE_ACCESSORS(UAuraAttributeSet,ManaRegeneration)
	UFUNCTION()
	void OnRep_ManaRegeneration(const FGameplayAttributeData& OldArmorPiercing) const;
	
	//最大生命值 MaxHP
	UPROPERTY(BlueprintReadOnly,ReplicatedUsing = OnRep_MaxHealth,Category= "Vital Attibutes")
	FGameplayAttributeData MaxHealth;
	ATTRIBUTE_ACCESSORS(UAuraAttributeSet,MaxHealth)
	UFUNCTION()
	void OnRep_MaxHealth(const FGameplayAttributeData& OldMaxHealth) const;

	
	//最大法力值 MaxMP
	UPROPERTY(BlueprintReadOnly,ReplicatedUsing = OnRep_MaxMana,Category= "Vital Attibutes")
	FGameplayAttributeData MaxMana;
	ATTRIBUTE_ACCESSORS(UAuraAttributeSet,MaxMana)
	UFUNCTION()
	void OnRep_MaxMana(const FGameplayAttributeData& OldMaxMana) const;

	
	/*
	 * Vital Attributes（至关重要的）
	 */
	//健康值 HP
	UPROPERTY(BlueprintReadOnly,ReplicatedUsing = OnRep_Health,Category= "Vital Attibutes")
	FGameplayAttributeData Health;
	ATTRIBUTE_ACCESSORS(UAuraAttributeSet,Health)
	UFUNCTION()
	void OnRep_Health(const FGameplayAttributeData& OldHealth) const;

	//法力值 MP
	UPROPERTY(BlueprintReadOnly,ReplicatedUsing = OnRep_Mana,Category= "Vital Attibutes")
	FGameplayAttributeData Mana;
	ATTRIBUTE_ACCESSORS(UAuraAttributeSet,Mana)
	UFUNCTION()
	void OnRep_Mana(const FGameplayAttributeData& OldMana) const;

	/**
	 * Meta Attribute
	 */
	//用于追踪游戏中角色受到的伤害。
	UPROPERTY(BlueprintReadOnly,Category= "Meta Attibutes")
	FGameplayAttributeData IncomingDamage;
	ATTRIBUTE_ACCESSORS(UAuraAttributeSet,IncomingDamage);
private:
	void SetEffectProperties(const FGameplayEffectModCallbackData& Data,FEffectProperties& SourceProps,FEffectProperties& TargetProps)const;
	UPROPERTY()
	FGameplayEffectContextHandle EffectContextHandle;
};
